﻿#define VK_USE_PLATFORM_WIN32_KHR
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>

#include <iostream>
#include <assert.h>
#include <vector>
#include <set>
#include <fstream>

#include <windows.h>
#include <vulkan/vulkan_win32.h>

const bool ENABLE_VALID_LAYER = true;
const int MAX_FRAMES_IN_FLIGHT = 2;

VkInstance g_vkInstance;
VkDebugUtilsMessengerEXT g_debugMessenger;
std::vector<VkExtensionProperties> g_vecInstanceExt;
std::vector<VkLayerProperties> g_vecLayerProp;

struct QueueFamilyInfo {
	VkQueueFamilyProperties properties;     // 队列族的属性
	VkBool32 surfaceSupport;        // 该队列族 是否支持 "呈现到Surface"
};
struct PhysicalDeviceInfo {
	VkPhysicalDevice physicalDevice;                // 物理设备句柄
	VkPhysicalDeviceProperties properties;  // 属性
	VkPhysicalDeviceFeatures features;      // 特征
	std::vector<VkExtensionProperties> vecExtension;    // 物理设备扩展
	std::vector<QueueFamilyInfo> vecQueueFamily;        // 队列族 列表
};
std::vector<PhysicalDeviceInfo> g_vecPhysicalDevice;

VkSurfaceKHR g_surface;

PhysicalDeviceInfo g_physicalDevice;        // 物理设备

// 交换链信息
struct SwapChainInfo {
	VkSurfaceCapabilitiesKHR caps;
	std::vector<VkSurfaceFormatKHR> formats;        // 像素格式 和 颜色空间
	std::vector<VkPresentModeKHR> modes;       // 呈现模式: 
		// VK_PRESENT_MODE_IMMEDIATE_KHR: 立即模式, 应用程序提交的图像会被立即传输到屏幕上，可能会导致撕裂现象
		// VK_PRESENT_MODE_FIFO_KHR     队列模式: 渲染结果放到队尾, 显示呈现从队首取, 队列满了 需要等待 (该模式默认必须存在)
		// VK_PRESENT_MODE_FIFO_RELAXED_KHR 宽松队列模式: 当呈现速度 快于 渲染速度, 可能出现 呈现正在渲染的图像(会有撕裂现象)
		// VK_PRESENT_MODE_MAILBOX_KHR  邮件队列模式: 当渲染速度 快于 呈现速度 导致 队列满了, 并不会等待, 而是直接替换队列(应该是队尾)中的图像, 该模式最优, 即不会撕裂, 还能避免延时
		// 实测 Win10-inteli5 只有 前两种模式
};
SwapChainInfo g_swapChainInfo;
VkFormat g_swapChainImageFormat;
VkExtent2D g_swapChainExtent;

VkSwapchainKHR g_swapChain;
std::vector<VkImage> g_vecSwapImage;
std::vector<VkImageView> g_vecImageView;

VkDevice g_device;        // 逻辑设备
VkQueue g_graphicsQueue;      // 图形队列
// VkQueue g_graphicsQueue1;     // 图形队列1
VkQueue g_presentQueue;       // 呈现队列
// VkQueue g_presentQueue1;      // 呈现队列1

GLFWwindow* g_window;

uint32_t g_indexOfGraphicsQueueFamily;    // 图形指令的队列族 索引
uint32_t g_indexOfPresentQueueFamily;     // 呈现指令的队列族 索引


VkRenderPass g_renderPass;
VkPipelineLayout g_pipelineLayout;		// 管线布局
VkPipeline g_graphicsPipeline;		// 管线

std::vector<VkFramebuffer> g_swapChainFramebuffers;		// 帧缓冲

VkCommandPool g_commandPool;		// 指令池: 它是 指令缓冲对象 的 管理器
std::vector<VkCommandBuffer> g_commandBuffers;	// 指令缓冲, 交换链上的每一个 Image 对应一个 指令缓冲

std::vector<VkSemaphore> g_imageAvailableSemaphores;
std::vector<VkSemaphore> g_renderFinishedSemaphores;
std::vector<VkFence> g_inFlightFences;

static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
	std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
	return VK_FALSE;
}

static void framebufferResizeCallback(GLFWwindow* window, int width, int height);

void createWindow() 
{
	// 初始化 glfw
	auto iResult = glfwInit(); assert(iResult == GLFW_TRUE);

	// 屏蔽 glfw 在创建 窗口时, 对 OpenGL 上下文的初始化
	glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

	// >>>>> [创建] 窗口
	g_window = glfwCreateWindow(800, 600, "Vulkan g_window", nullptr, nullptr);

	glfwSetFramebufferSizeCallback(g_window, framebufferResizeCallback);
}

void createInstance()
{
	// ?
	uint32_t pApiVersion; VkResult vResult = vkEnumerateInstanceVersion(&pApiVersion); assert(vResult == VK_SUCCESS);

	// 枚举 所有 VkInstance扩展
	{
		uint32_t extensionCount = 0;
		vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
		std::vector<VkExtensionProperties> extensions(extensionCount);
		vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
	}

	// 设定 创建 VkInstance 时需要 启用 的扩展
	std::vector<const char*> vecEnabledInstanceExt;
	{
		// 从 glfw 中 可以拿到 glfw 窗口系统必须要的 扩展 
		// eg: Windows 上为 {"VK_KHR_surface", "VK_KHR_win32_surface"}
		uint32_t glfwExtensionCount;
		const char** extNeedByGLFW = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
		for (uint32_t i = 0; i < glfwExtensionCount; ++i) {
			vecEnabledInstanceExt.push_back(extNeedByGLFW[i]);
		}

		// 额外加入: 调试工具扩展
		if (ENABLE_VALID_LAYER) {
			vecEnabledInstanceExt.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
		}

		// TODO: 需要验证 启动的扩展 都在 之前枚举之中
	}

	// 枚举所有 VkInstance层
	{
		uint32_t layerCount;
		vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
		g_vecLayerProp.resize(layerCount);
		vkEnumerateInstanceLayerProperties(&layerCount, g_vecLayerProp.data());
	}

	// 设定 创建 VkInstance 时需要启动的 层
	std::vector<const char*> vecEnabledLayer;
	{
		// 启用 验证层
		if (ENABLE_VALID_LAYER) {
			vecEnabledLayer.push_back("VK_LAYER_KHRONOS_validation");
		}

		// TODO: 需要验证 启动的层 都在 之前枚举之中
	}

	// 构造 "应用信息"
	VkApplicationInfo appInfo{}; {
		appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
		appInfo.pApplicationName = "Hello Triangle";                // app 和 engine 的 name 与 version 字段 用于 驱动可能的针对性优化
		appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
		appInfo.pEngineName = "No Engine";
		appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
		appInfo.apiVersion = VK_API_VERSION_1_2;                // ?
	}

	// 构造 "实例创建信息"
	VkInstanceCreateInfo createInfo{}; {
		createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
		createInfo.pApplicationInfo = &appInfo;
		createInfo.enabledExtensionCount = (uint32_t)vecEnabledInstanceExt.size();      // 需要启用的扩展
		createInfo.ppEnabledExtensionNames = vecEnabledInstanceExt.data();
		createInfo.enabledLayerCount = (uint32_t)vecEnabledLayer.size();                       // 需要启用的层
		createInfo.ppEnabledLayerNames = vecEnabledLayer.data();
	}

	// >>>>> [创建] Vulkan实例
	vResult = vkCreateInstance(&createInfo, nullptr, &g_vkInstance);
	assert(vResult == VK_SUCCESS);

	// 为 "Vulkan实例" 创建时 启用的 "校验层" 配置 "消息接收器"
	if (ENABLE_VALID_LAYER)
	{
		// vkCreateDebugUtilsMessengerEXT 该函数可能需要使用 vkGetInstanceProcAddr 获得
		auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(g_vkInstance, "vkCreateDebugUtilsMessengerEXT"); assert(func != nullptr);

		VkDebugUtilsMessengerCreateInfoEXT info{}; {
			info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
			// 消息级别
			info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
			// 消息类型
			info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
			// 回调函数地址
			info.pfnUserCallback = debugCallback;
			// 用户字段
			info.pUserData = nullptr; // Optional
		}

		// 设定它, 返回了 一个 VkDebugUtilsMessengerEXT, 需要在 销毁 Vulkan 实例前 销毁它
		vResult = func(g_vkInstance, &info, nullptr, &g_debugMessenger);
		assert(vResult == VK_SUCCESS);
	}

}

void createDevice()
{
	// 3. 创建 VkSurfaceKHR
	{
		// 方式1: 平台特定编码
		//VkWin32SurfaceCreateInfoKHR createSurfaceInfo = {};
		//createSurfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
		//createSurfaceInfo.hinstance = GetModuleHandle(nullptr);
		//createSurfaceInfo.hwnd = glfwGetWin32Window(window);
		//result = vkCreateWin32SurfaceKHR(g_vkInstance, &createSurfaceInfo, nullptr, &surface);
		//assert(result == VK_SUCCESS);

		// 方式2: 使用 glfw
		auto vResult = glfwCreateWindowSurface(g_vkInstance, g_window, nullptr, &g_surface);
		assert(vResult == VK_SUCCESS);
	}

	// 枚举 所有 物理设备
	{
		uint32_t physicalDeviceCount;
		vkEnumeratePhysicalDevices(g_vkInstance, &physicalDeviceCount, nullptr);
		std::vector<VkPhysicalDevice> vecPhysicalDevice(physicalDeviceCount);
		vkEnumeratePhysicalDevices(g_vkInstance, &physicalDeviceCount, vecPhysicalDevice.data());
	}

	// 选择 物理设备 和 队列族 索引
	{
		uint32_t physicalDeviceCount;
		auto vResult = vkEnumeratePhysicalDevices(g_vkInstance, &physicalDeviceCount, nullptr); assert(vResult == VK_SUCCESS);
		std::vector<VkPhysicalDevice> vecPhysicalDevice(physicalDeviceCount);
		vResult = vkEnumeratePhysicalDevices(g_vkInstance, &physicalDeviceCount, vecPhysicalDevice.data()); assert(vResult == VK_SUCCESS);

		g_vecPhysicalDevice.resize(physicalDeviceCount);
		for (auto itor = vecPhysicalDevice.begin(); itor != vecPhysicalDevice.end(); ++itor)
		{
			auto device = *itor;
			auto& info = g_vecPhysicalDevice[itor - vecPhysicalDevice.begin()];
			info.physicalDevice = device;

			// 设备 属性
			vkGetPhysicalDeviceProperties(device, &info.properties);

			// 设备 特征
			vkGetPhysicalDeviceFeatures(device, &info.features);

			// 设备 支持的扩展
			uint32_t deviceExtensionCount;
			vResult = vkEnumerateDeviceExtensionProperties(device, nullptr, &deviceExtensionCount, nullptr); assert(vResult == VK_SUCCESS);        // layerName ?
			info.vecExtension.resize(deviceExtensionCount);
			vResult = vkEnumerateDeviceExtensionProperties(device, nullptr, &deviceExtensionCount, info.vecExtension.data()); assert(vResult == VK_SUCCESS);

			// 获取 设备的 队列族 列表
			uint32_t queueFamilyCount = 0;
			vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
			std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
			vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
			info.vecQueueFamily.resize(queueFamilyCount);
			for (auto itorF = queueFamilies.begin(); itorF != queueFamilies.end(); ++itorF) {
				auto indexOfQueueFamily = itorF - queueFamilies.begin();
				const auto& p = *itorF;
				auto& infoQ = info.vecQueueFamily[indexOfQueueFamily];
				infoQ.properties = p;

				// 队列族 是否支持 "呈现到Surface"
				vResult = vkGetPhysicalDeviceSurfaceSupportKHR(device, (uint32_t)indexOfQueueFamily, g_surface, &infoQ.surfaceSupport);
				assert(vResult == VK_SUCCESS);
			}
		}

		// 选定 物理设备 和 队列族 索引 (实际代码需要根据 验证结果来选择)
		g_physicalDevice = g_vecPhysicalDevice.front();
		g_indexOfGraphicsQueueFamily = 0;
		g_indexOfPresentQueueFamily = 0;

		// 验证 "图形队列族" 支持 图形指令
		assert(g_physicalDevice.vecQueueFamily[g_indexOfGraphicsQueueFamily].properties.queueFlags & VK_QUEUE_GRAPHICS_BIT);

		// 验证 "呈现队列族" 支持 SurfaceKHR 扩展
		assert(g_physicalDevice.vecQueueFamily[g_indexOfPresentQueueFamily].surfaceSupport == VK_TRUE);

		// 验证 物理设备 支持 "交换链"
		assert(std::find_if(g_physicalDevice.vecExtension.begin(), g_physicalDevice.vecExtension.end(), [](const VkExtensionProperties& prop) { return strcmp(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0; }) != g_physicalDevice.vecExtension.end());
	}

	// [创建] 逻辑设备
	{
		// 配置 该逻辑设备的 队列属性
		// 注: queueFamilyIndex 相同的 需要合并
		//      实际测试 发现 如果不合并, 在 queueCreateInfo 中有两个重复的 queueFamilyIndex 元素, Windows 上的结果是以后一个为准
		std::vector<VkDeviceQueueCreateInfo> vecCreateQueueInfo; {
			std::set<uint32_t> vecQueueFamilyIndex = { g_indexOfGraphicsQueueFamily, g_indexOfPresentQueueFamily };
			for (auto itor = vecQueueFamilyIndex.begin(); itor != vecQueueFamilyIndex.end(); ++itor) {
				const auto queueFamilyIndex = *itor;
				vecCreateQueueInfo.push_back(VkDeviceQueueCreateInfo());
				auto& queueCreateInfo = vecCreateQueueInfo.back();
				queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
				queueCreateInfo.queueFamilyIndex = queueFamilyIndex;       // 为选中的队列族 在 queueFamilies 中的索引
				static const float queuesPriority[] = { 1.0f };
				queueCreateInfo.queueCount = sizeof(queuesPriority) / sizeof(float);    // 要创建的队列数, 一般只需一个(即使是在多线程环境下)
				queueCreateInfo.pQueuePriorities = queuesPriority;      // 每个队列的优先级, 只有1个队列, 也要赋值    
			}
		}
		// ?
		VkPhysicalDeviceFeatures deviceFeatures = {};

		// 配置 逻辑设备属性        
		std::vector<const char*> vecEnabledLayer; {
			// 启用 验证层
			if (ENABLE_VALID_LAYER) {
				vecEnabledLayer.push_back("VK_LAYER_KHRONOS_validation");
			}
		}
		VkDeviceCreateInfo createDeviceInfo = {};
		{
			createDeviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

			// 队列信息, 这里可包含多个 createDeviceInfo, 而且 看 VkDeviceQueueCreateInfo 的描述, 它里面也可以表示多个
			createDeviceInfo.queueCreateInfoCount = (uint32_t)vecCreateQueueInfo.size();
			createDeviceInfo.pQueueCreateInfos = vecCreateQueueInfo.data();

			createDeviceInfo.pEnabledFeatures = &deviceFeatures;

			// 启用哪些扩展
			static const char* deviceExts[] = {
				VK_KHR_SWAPCHAIN_EXTENSION_NAME         // 设备 需要 支持交换链
			};
			createDeviceInfo.enabledExtensionCount = sizeof(deviceExts) / sizeof(const char*);
			createDeviceInfo.ppEnabledExtensionNames = deviceExts;

			// 校验层还要再设置一次?
			createDeviceInfo.enabledLayerCount = (uint32_t)vecEnabledLayer.size();
			createDeviceInfo.ppEnabledLayerNames = vecEnabledLayer.data();
		}

		// 创建 逻辑设备(同时也会创建逻辑队列)
		auto vResult = vkCreateDevice(g_physicalDevice.physicalDevice, &createDeviceInfo, nullptr, &g_device);
		assert(vResult == VK_SUCCESS);

		// 然后从 创建的 逻辑设备 中 拿到 逻辑队列句柄
		vkGetDeviceQueue(g_device, g_indexOfGraphicsQueueFamily, 0, &g_graphicsQueue);
		vkGetDeviceQueue(g_device, g_indexOfPresentQueueFamily, 0, &g_presentQueue);
	}

}

void createSwapChain()
{
	vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_physicalDevice.physicalDevice, g_surface, &g_swapChainInfo.caps);

	uint32_t formatCount;
	vkGetPhysicalDeviceSurfaceFormatsKHR(g_physicalDevice.physicalDevice, g_surface, &formatCount, nullptr);
	g_swapChainInfo.formats.resize(formatCount);
	vkGetPhysicalDeviceSurfaceFormatsKHR(g_physicalDevice.physicalDevice, g_surface, &formatCount, g_swapChainInfo.formats.data());

	uint32_t modeCount;
	vkGetPhysicalDeviceSurfacePresentModesKHR(g_physicalDevice.physicalDevice, g_surface, &modeCount, nullptr);
	g_swapChainInfo.modes.resize(modeCount);
	vkGetPhysicalDeviceSurfacePresentModesKHR(g_physicalDevice.physicalDevice, g_surface, &modeCount, g_swapChainInfo.modes.data());

	// 需要 确保 "这个surface" 在 这个"物理设备" 上的 交换链 的 "格式" 和 "模式" 有值
	assert(g_swapChainInfo.formats.size() && g_swapChainInfo.modes.size());

	// 确定 交换链中 图像个数
	uint32_t imageCount;
	{
		// minImageCount 一般为2, 这里实现 3 缓冲
		imageCount = g_swapChainInfo.caps.minImageCount + 1;
		// 同时需要保证 不能大于 maxImageCount( 有个例外, 当 maxImageCount 为 0, 意味着 只要内存够用 可以用无限多个 缓冲区 )
		if (g_swapChainInfo.caps.maxImageCount > 0 && imageCount > g_swapChainInfo.caps.maxImageCount) {
			imageCount = g_swapChainInfo.caps.maxImageCount;
		}
	}

	// 选择 format, TODO: 需要确保 该项 存在 于 formats 列表 中
	VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
	g_swapChainImageFormat = surfaceFormat.format;

	// 选择 mode, TODO: 如果可以 应该优选 VK_PRESENT_MODE_MAILBOX_KHR
	VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

	// image 大小(分辨率), 直接使用当前
	g_swapChainExtent = g_swapChainInfo.caps.currentExtent;

	VkSwapchainCreateInfoKHR createSwapChainInfo = {};
	createSwapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
	createSwapChainInfo.surface = g_surface;
	createSwapChainInfo.minImageCount = imageCount;         // 指定 交换链上 的 最少 image 数(实际Vulkan实现会大于等于该值)
	createSwapChainInfo.imageFormat = surfaceFormat.format;
	createSwapChainInfo.imageColorSpace = surfaceFormat.colorSpace;
	createSwapChainInfo.imageExtent = g_swapChainExtent;
	createSwapChainInfo.imageArrayLayers = 1;       // 指定每个 图像 的层次(类似 mipmap, 多用于VR)
	createSwapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;   // 设定用法: 即作为 颜色附加 来使用
			// VK_IMAGE_USAGE_TRANSFER_DST_BIT  表示 可作为 拷贝目的地

	// 设值 交换链的 之于 队列 的共享模式
	if (g_indexOfGraphicsQueueFamily == g_indexOfPresentQueueFamily) {
		createSwapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;    // 交换链为独占, 别的队列要使用 必须显示改变所有权
		createSwapChainInfo.pQueueFamilyIndices = nullptr;  // 置空即可
		createSwapChainInfo.queueFamilyIndexCount = 0;      // 设0即可
	} else {
		createSwapChainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;  // 协同模式, 当 图形绘制队列 与 呈现队列 不是一个时, 就指定这个
		static uint32_t indices[] = { g_indexOfGraphicsQueueFamily, g_indexOfPresentQueueFamily };
		createSwapChainInfo.pQueueFamilyIndices = indices;
		createSwapChainInfo.queueFamilyIndexCount = 2;
	}

	// 可以设置一个固定的 旋转/翻转 模式, 这里就用默认
	createSwapChainInfo.preTransform = g_swapChainInfo.caps.currentTransform;

	// 用于设置 与 窗口系统中 其他窗口的 alpha 混合模式
	createSwapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // 设置为不混合

	createSwapChainInfo.presentMode = presentMode;

	// clipped 成员变量被设置为 VK_TRUE 表示我们不关心被窗口系统中的其它窗口遮挡的像素的颜色， 
	// 这允许 Vulkan 采取一定的优化措施，但如果我们回读窗口的像素值就可能出现问题
	createSwapChainInfo.clipped = VK_TRUE;

	// 之前的交换链, 作用是 当 交换链失效后(如窗口大小改变), 用于重建新的交换链
	createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE;

	auto vResult = vkCreateSwapchainKHR(g_device, &createSwapChainInfo, nullptr, &g_swapChain);
	assert(vResult == VK_SUCCESS);

	// 获取 交换链 上的 image
	// 说明: 在创建 交换链时 设置 的 minImageCount 为最小image个数, 实际Vulkan实现会大于等于该值, 这里返回的 imageCount 为实际值
	{
		uint32_t cnt;
		vResult = vkGetSwapchainImagesKHR(g_device, g_swapChain, &cnt, nullptr); assert(vResult == VK_SUCCESS);
		g_vecSwapImage.resize(cnt);
		vResult = vkGetSwapchainImagesKHR(g_device, g_swapChain, &cnt, g_vecSwapImage.data()); assert(vResult == VK_SUCCESS);
	}

	// [创建] ImageView
	{
		g_vecImageView.resize(g_vecSwapImage.size());
		for (auto itor = g_vecImageView.begin(); itor != g_vecImageView.end(); ++itor) {

			auto& imageView = *itor;
			const auto& image = g_vecSwapImage[itor - g_vecImageView.begin()];

			VkImageViewCreateInfo viewInfo = {};
			viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
			viewInfo.image = image;
			viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;      // 指定将 image 看作 什么类型
			viewInfo.format = g_swapChainImageFormat;       // 指定 格式

			// ?指定每个颜色通道的 映射
			viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
			viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
			viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
			viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;

			// ?方面(如:颜色,深度,模板)
			viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

			// mipmap
			viewInfo.subresourceRange.baseMipLevel = 0;
			viewInfo.subresourceRange.levelCount = 1;

			// 层, 用于AR, 如 左眼图像, 右眼图像
			viewInfo.subresourceRange.baseArrayLayer = 0;
			viewInfo.subresourceRange.layerCount = 1;

			// 创建 ImgaeView
			auto vResult = vkCreateImageView(g_device, &viewInfo, nullptr, &imageView);
			assert(vResult == VK_SUCCESS);
		}
	}

}

void createPipeline() 
{

	// 着色器阶段 列表
	VkPipelineShaderStageCreateInfo shaderStages[2];
	VkShaderModule vertShaderModule, fragShaderModule;
	{
		struct CreateShaderModule {
			VkShaderModule operator()(const char* spvFilename) {
				auto code = readFile(spvFilename);
				VkShaderModuleCreateInfo info = {};
				info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
				info.codeSize = code.size();
				info.pCode = reinterpret_cast<const uint32_t*>(code.data());
				VkShaderModule shaderModule;
				auto vResult = vkCreateShaderModule(g_device, &info, nullptr, &shaderModule);
				assert(vResult == SCARD_S_SUCCESS);
				return shaderModule;
			}
			static std::vector<char> readFile(const std::string& filename) {
				std::ifstream file(filename, std::ios::ate | std::ios::binary);
				if (!file.is_open()) { throw std::runtime_error("failed to open file!"); }
				size_t fileSize = (size_t)file.tellg();
				std::vector<char> buffer(fileSize);
				file.seekg(0);
				file.read(buffer.data(), fileSize);
				file.close();
				return buffer;
			}
		} createShaderModule;

		// VkShaderModule 只是字节码的简单包装
		vertShaderModule = createShaderModule("./shader.vert.spv");
		fragShaderModule = createShaderModule("./shader.frag.spv");

		// 顶点着色器 的 阶段创建 信息
		VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
		vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
		vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;		// 用在 顶点着色 阶段
		vertShaderStageInfo.module = vertShaderModule;		// 设定 VkShaderModule
		vertShaderStageInfo.pName = "main";			// 设定 入口函数
		vertShaderStageInfo.pSpecializationInfo = nullptr;		// 可用于指定着色器用到的常量, 有利于分支的静态优化

		// 片元着色器 的 阶段创建 信息
		VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
		fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
		fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;		// 用在 片元着色 阶段
		fragShaderStageInfo.module = fragShaderModule;		// 设定 VkShaderModule
		fragShaderStageInfo.pName = "main";			// 设定 入口函数
		fragShaderStageInfo.pSpecializationInfo = nullptr;		// 可用于指定着色器用到的常量, 有利于分支的静态优化

		shaderStages[0] = vertShaderStageInfo;
		shaderStages[1] = fragShaderStageInfo;
	}

	// 固定功能状态: 顶点数据格式
	VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
	{
		vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
		// 顶点 绑定描述列表
		vertexInputInfo.vertexBindingDescriptionCount = 0;
		vertexInputInfo.pVertexBindingDescriptions = nullptr;
		// 顶点 属性描述列表
		vertexInputInfo.vertexAttributeDescriptionCount = 0;
		vertexInputInfo.pVertexAttributeDescriptions = nullptr;

	}

	// 固定功能状态: 顶点装配信息 
	VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
	{
		inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
		// 图元类型, 点, 连续线, 三角形列表 等待
		inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
		// 是否使用 "图元装配重启"
		// 通过一个特殊索引值 0xFFFF 或 0xFFFFFFFF, 达到重启图元的目的
		inputAssembly.primitiveRestartEnable = VK_FALSE;
	}

	// 固定功能状态: 视口 与 剪裁
	VkPipelineViewportStateCreateInfo viewportState = {};
	{
		// 视口
		VkViewport viewport = {};
		viewport.x = 0.0f;
		viewport.y = 0.0f;
		// Viewport 宽高 是根据 交换链的 范围来的 而不是窗口
		viewport.width = (float)g_swapChainExtent.width;
		viewport.height = (float)g_swapChainExtent.height;
		viewport.minDepth = 0.0f;
		viewport.maxDepth = 1.0f;

		// 剪裁
		VkRect2D scissor = {};
		scissor.offset = { 0 , 0 };
		scissor.extent = g_swapChainExtent;

		viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
		viewportState.viewportCount = 1;
		viewportState.pViewports = &viewport;
		viewportState.scissorCount = 1;
		viewportState.pScissors = &scissor;
	}

	// 固定功能状态: 光栅化 配置
	VkPipelineRasterizationStateCreateInfo rasterizer = {};
	{
		rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
		// depthClampEnable 成员变量设置为 VK_TRUE 表示
		//		在 近平面 和 远平面 外的片段 会被 截断为 在近平面和远平面上，而不是直接丢弃这些片段
		// 这对于阴影贴图的生成很有用
		rasterizer.depthClampEnable = VK_FALSE;

		// rasterizerDiscardEnable 成员变量设置为 VK_TRUE 表示所有几何图
		//		元都不能通过光栅化阶段。这一设置会禁止一切片段输出到帧缓冲
		rasterizer.rasterizerDiscardEnable = VK_FALSE;

		// 填充模式, 点, 线框, 面
		rasterizer.polygonMode = VK_POLYGON_MODE_FILL;

		// 线宽
		rasterizer.lineWidth = 1.0f;

		// 背面剔除
		rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;

		// 正面环绕方向
		rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;

		// 多边形偏移
		rasterizer.depthBiasEnable = VK_FALSE;
		rasterizer.depthBiasConstantFactor = 0.0f; // Optional
		rasterizer.depthBiasClamp = 0.0f; // Optional
		rasterizer.depthBiasSlopeFactor = 0.0f; // Optional

	}

	// 固定功能状态: 多重采样
	VkPipelineMultisampleStateCreateInfo multisampling = {};
	{
		multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
		multisampling.sampleShadingEnable = VK_FALSE;
		multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
		multisampling.minSampleShading = 1.0f; // Optional
		multisampling.pSampleMask = nullptr; // Optional
		multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
		multisampling.alphaToOneEnable = VK_FALSE; // Optional
	}

	// 固定功能状态: 深度测试, 模板测试
	// VkPipelineDepthStencilStateCreateInfo 

	// 固定功能状态: 融混 与 逻辑运算
	VkPipelineColorBlendStateCreateInfo colorBlending{};
	VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
	{
		// VkPipelineColorBlendAttachmentState	// 用于单独设置每个 帧缓冲
		// VkPipelineColorBlendStateCreateInfo	// 用于全局设置 渲染管线的 所有帧缓冲

		colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
		colorBlendAttachment.blendEnable = VK_FALSE;
		colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
		colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
		colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; //Optional
		colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
		colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
		colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional

		colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
		colorBlending.logicOpEnable = VK_FALSE;
		colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
		colorBlending.attachmentCount = 1;
		colorBlending.pAttachments = &colorBlendAttachment;
		colorBlending.blendConstants[0] = 0.0f; // Optional
		colorBlending.blendConstants[1] = 0.0f; // Optional
		colorBlending.blendConstants[2] = 0.0f; // Optional
		colorBlending.blendConstants[3] = 0.0f; // Optional

	}

	// 固定功能状态: 动态状态: 为某些 可以 在创建完管线后 随时修改的 状态
	// ? 如何修改呢?
	VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_LINE_WIDTH };
	VkPipelineDynamicStateCreateInfo dynamicState{};
	{
		dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
		dynamicState.dynamicStateCount = 2;
		dynamicState.pDynamicStates = dynamicStates;
	}

	// 创建 管线布局, 用于配置 uniform 变量
	{
		VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
		pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
		pipelineLayoutInfo.setLayoutCount = 0; // Optional
		pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
		pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
		pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
		auto vResult = vkCreatePipelineLayout(g_device, &pipelineLayoutInfo, nullptr, &g_pipelineLayout);
		assert(vResult == VK_SUCCESS);
	}


	// 创建 renderPass
	{
		// attachment 描述
		VkAttachmentDescription colorAttachment = {};
		{
			colorAttachment.format = g_swapChainImageFormat;
			colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;		// 没有使用 多重采样

			// 指定 渲染前的 操作 ( 对颜色和深度缓冲起效 )
			// VK_ATTACHMENT_LOAD_OP_LOAD：保持附着的现有内容
			// VK_ATTACHMENT_LOAD_OP_CLEAR：使用一个常量值来清除附着的内容
			// VK_ATTACHMENT_LOAD_OP_DONT_CARE：不关心附着现存的内容
			colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;

			// 指定 渲染后的 操作 ( 对颜色和深度缓冲起效 )
			// VK_ATTACHMENT_STORE_OP_STORE：渲染的内容会被存储起来，以便之后读取
			// VK_ATTACHMENT_STORE_OP_DONT_CARE：渲染后，不会读取帧缓冲的内容
			colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;

			// 指定 模板缓冲 渲染前后的 操作 
			colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
			colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;

			// 指定 布局 (用法)
			//	很费解 布局 这个词, 这里可以设置的值为 
			// 查看 VkImageLayout 的枚举值 文档, 应该叫 设定 attachment 的 用法比较合理
			// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL：图像被用作颜色附着
			// VK_IMAGE_LAYOUT_PRESENT_SRC_KHR：图像被用在交换链中进行呈现操作
			// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL：图像被用作复制操作的目的图像
			colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
			colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;	// 使得渲染后的图像可以被交换链呈现
		}

		// attachment ref
		// 它直接 对应 片元着色器代码 中的 out 变量
		VkAttachmentReference colorAttachmentRef = {};
		{
			colorAttachmentRef.attachment = 0;
			colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
		}

		// 子流程描述
		VkSubpassDescription subpass = {};
		{
			subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
			subpass.colorAttachmentCount = 1;
			subpass.pColorAttachments = &colorAttachmentRef;
		}

		VkSubpassDependency dependency{};
		dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
		dependency.dstSubpass = 0;
		dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
		dependency.srcAccessMask = 0;
		dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
		dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

		// 
		VkRenderPassCreateInfo renderPassInfo{};
		renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
		renderPassInfo.attachmentCount = 1;
		renderPassInfo.pAttachments = &colorAttachment;
		renderPassInfo.subpassCount = 1;
		renderPassInfo.pSubpasses = &subpass;
		renderPassInfo.dependencyCount = 1;
		renderPassInfo.pDependencies = &dependency;

		auto vResult = vkCreateRenderPass(g_device, &renderPassInfo, nullptr, &g_renderPass);
		assert(VK_SUCCESS == vResult);
	}


	// 创建 管线
	{
		VkGraphicsPipelineCreateInfo pipelineInfo{};
		pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
		pipelineInfo.stageCount = 2;
		pipelineInfo.pStages = shaderStages;
		pipelineInfo.pVertexInputState = &vertexInputInfo;
		pipelineInfo.pInputAssemblyState = &inputAssembly;
		pipelineInfo.pViewportState = &viewportState;
		pipelineInfo.pRasterizationState = &rasterizer;
		pipelineInfo.pMultisampleState = &multisampling;
		pipelineInfo.pDepthStencilState = nullptr; // Optional
		pipelineInfo.pColorBlendState = &colorBlending;
		pipelineInfo.pDynamicState = nullptr; // Optional
		pipelineInfo.layout = g_pipelineLayout;
		pipelineInfo.renderPass = g_renderPass;
		pipelineInfo.subpass = 0;		// 子流程索引
		pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // 之前的 管线
		pipelineInfo.basePipelineIndex = -1; // Optional


		auto vResult = vkCreateGraphicsPipelines(g_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &g_graphicsPipeline);
		assert(vResult == VK_SUCCESS);
	}

	// 可以立刻删除 VkShaderModule
	vkDestroyShaderModule(g_device, vertShaderModule, nullptr);
	vkDestroyShaderModule(g_device, fragShaderModule, nullptr);
}

void createFramebuffers() 
{
	g_swapChainFramebuffers.resize(g_vecImageView.size());

	for (size_t i = 0; i < g_swapChainFramebuffers.size(); i++) {
		VkImageView attachments[] = { g_vecImageView[i] };

		VkFramebufferCreateInfo framebufferInfo{};
		framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
		framebufferInfo.renderPass = g_renderPass;			// 指定渲染流程
		framebufferInfo.attachmentCount = 1;			// 指定 attachment
		framebufferInfo.pAttachments = attachments;
		framebufferInfo.width = g_swapChainExtent.width;
		framebufferInfo.height = g_swapChainExtent.height;
		framebufferInfo.layers = 1;

		auto vResult = vkCreateFramebuffer(g_device, &framebufferInfo, nullptr, &g_swapChainFramebuffers[i]);
		assert(vResult == VK_SUCCESS);
	}
}

void createCommandBuffers() {
	// 创建 指令池
	if (g_commandPool == nullptr) {
		VkCommandPoolCreateInfo poolInfo{};
		poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
		poolInfo.queueFamilyIndex = g_indexOfGraphicsQueueFamily;
		poolInfo.flags = 0; // Optional	
		auto vResult = vkCreateCommandPool(g_device, &poolInfo, nullptr, &g_commandPool);
		assert(vResult == VK_SUCCESS);
	}

	// 分配 指令缓冲, 每个 ImageView 对应一个
	g_commandBuffers.resize(g_vecImageView.size());
	VkCommandBufferAllocateInfo allocInfo{};
	allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
	allocInfo.commandPool = g_commandPool;
	allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
	allocInfo.commandBufferCount = (uint32_t)g_commandBuffers.size();
	auto vResult = vkAllocateCommandBuffers(g_device, &allocInfo, g_commandBuffers.data());
	assert(vResult == VK_SUCCESS);

	// 开始 录制指令
	for (size_t i = 0; i < g_commandBuffers.size(); i++) {
		VkCommandBufferBeginInfo beginInfo{};
		beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
		beginInfo.flags = 0; // Optional
		beginInfo.pInheritanceInfo = nullptr; // Optional

		// 开始 录制指令
		vResult = vkBeginCommandBuffer(g_commandBuffers[i], &beginInfo); assert(vResult == VK_SUCCESS);

		// 开始渲染流程
		VkRenderPassBeginInfo renderPassInfo{};
		renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
		renderPassInfo.renderPass = g_renderPass;
		renderPassInfo.framebuffer = g_swapChainFramebuffers[i];
		renderPassInfo.renderArea.offset = { 0, 0 };
		renderPassInfo.renderArea.extent = g_swapChainExtent;
		VkClearValue clearColor = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
		renderPassInfo.clearValueCount = 1;
		renderPassInfo.pClearValues = &clearColor;
		vkCmdBeginRenderPass(g_commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

		// 绘制指令
		{
			// 绑定图形管线
			vkCmdBindPipeline(g_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, g_graphicsPipeline);

			// Draw
			vkCmdDraw(g_commandBuffers[i], 3, 1, 0, 0);
		}

		// 结束
		vkCmdEndRenderPass(g_commandBuffers[i]);

		// 结束录制指令
		vResult = vkEndCommandBuffer(g_commandBuffers[i]); assert(vResult == VK_SUCCESS);

	}
}

void createSyncObject() {
	g_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
	g_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
	g_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
	for (auto i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {

		VkSemaphoreCreateInfo semaphoreInfo = {};
		semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
		auto vResult = vkCreateSemaphore(g_device, &semaphoreInfo, nullptr, &g_imageAvailableSemaphores[i]);
		assert(vResult == VK_SUCCESS);

		vResult = vkCreateSemaphore(g_device, &semaphoreInfo, nullptr, &g_renderFinishedSemaphores[i]);
		assert(vResult == VK_SUCCESS);

		VkFenceCreateInfo fenceInfo = {};
		fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
		fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
		vkCreateFence(g_device, &fenceInfo, nullptr, &g_inFlightFences[i]);
	}
}

void clearupSwapChainEtc() {
	// 销毁 FrameBuffer
	for (auto itor = g_swapChainFramebuffers.begin(); itor != g_swapChainFramebuffers.end(); ++itor) {
		VkFramebuffer fbo = *itor;
		vkDestroyFramebuffer(g_device, fbo, nullptr);
	}

	// 销毁 CommandBuffer
	vkFreeCommandBuffers(g_device, g_commandPool, (uint32_t)g_commandBuffers.size(), g_commandBuffers.data());

	// 销毁 Pipeline 和 PipelineLayout
	vkDestroyPipeline(g_device, g_graphicsPipeline, nullptr);
	vkDestroyPipelineLayout(g_device, g_pipelineLayout, nullptr);

	// 销毁 RenderPass
	vkDestroyRenderPass(g_device, g_renderPass, nullptr);

	// 销毁 ImageView
	for (auto itor = g_vecImageView.begin(); itor != g_vecImageView.end(); ++itor) {
		VkImageView imageView = *itor;
		vkDestroyImageView(g_device, imageView, nullptr);
	}

	// 销毁 Swapchain
	vkDestroySwapchainKHR(g_device, g_swapChain, nullptr);
}

void clearup() {
	// 销毁 SwapChain 相关
	clearupSwapChainEtc();

	// 销毁 renderOneFrame 时 用到的 同步对象
	for (auto i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
		vkDestroySemaphore(g_device, g_imageAvailableSemaphores[i], nullptr);
		vkDestroySemaphore(g_device, g_renderFinishedSemaphores[i], nullptr);
		vkDestroyFence(g_device, g_inFlightFences[i], nullptr);
	}

	// 销毁 CommandPool
	vkDestroyCommandPool(g_device, g_commandPool, nullptr);

	// 销毁 Device
	vkDestroyDevice(g_device, nullptr);

	// 销毁 Debug Messager
	if (ENABLE_VALID_LAYER)
	{
		auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)
			vkGetInstanceProcAddr(g_vkInstance, "vkDestroyDebugUtilsMessengerEXT");
		assert(func != nullptr);
		func(g_vkInstance, g_debugMessenger, nullptr);
	}

	// 销毁 Surface
	vkDestroySurfaceKHR(g_vkInstance, g_surface, nullptr);

	// 销毁 VkInstance
	vkDestroyInstance(g_vkInstance, nullptr);

	// 销毁 Window
	glfwDestroyWindow(g_window);

	// glfw 退出
	glfwTerminate();
}

void recreateSwapChain() {
	// 需要特殊处理 窗口最小化的情况
	int w = 0, h = 0;
	while (w == 0 || h == 0) {
		glfwWaitEvents();
		glfwGetFramebufferSize(g_window, &w, &h);
	}

	vkDeviceWaitIdle(g_device);

	clearupSwapChainEtc();

	createSwapChain();
	createPipeline();
	createFramebuffers();
	createCommandBuffers();
}

static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
	recreateSwapChain();
}

int main() {

	// 1. 创建 窗口
	createWindow();

	// 2. 创建 VkInstance
	createInstance();

	// 3. 创建 VkDevice
	createDevice();

	// 4. 创建 交换链, VkImageView
	createSwapChain();

	// 5. 创建 渲染管线
	createPipeline();

	// 6. 创建 帧缓冲
	createFramebuffers();

	// 7. 指令池 指令缓冲对象   队列 指令序列 提交执行  辅助指令缓冲对象
	createCommandBuffers();

	// renderOnFrame 时用到的 同步对象
	createSyncObject();

	// 事件循环

	LARGE_INTEGER fre, tStart, tEnd;
	QueryPerformanceFrequency(&fre);
	QueryPerformanceCounter(&tStart);
	int i = 0;
	int inFlightIndex = 0;
	while (!glfwWindowShouldClose(g_window)) {
		glfwPollEvents();

		// 这里的需要等待 上一个(应该说时上一组) Submit 的 CommandBuffer 执行完毕
		{
			auto vResult = vkWaitForFences(g_device, 1, &g_inFlightFences[inFlightIndex], VK_TRUE, std::numeric_limits<uint64_t>::max());
			assert(vResult == VK_SUCCESS);
			vResult = vkResetFences(g_device, 1, &g_inFlightFences[inFlightIndex]);
			assert(vResult == VK_SUCCESS);
		}

		// 从交换链获取一张图像索引
		uint32_t imageIndex;
		{
			// 貌似返回的永远都是上一次的 索引++ % imageCount
			auto vResult = vkAcquireNextImageKHR(g_device, g_swapChain,
				std::numeric_limits<uint64_t>::max(),	// 最大等待时间
				g_imageAvailableSemaphores[inFlightIndex],			// 当图像可用后 该信号量 会被设置
				VK_NULL_HANDLE,				// 栅栏
				&imageIndex);
			assert(vResult == VK_SUCCESS);
		}
		
		// 对帧缓冲附着执行指令缓冲中的渲染指令
		VkSemaphore signalSemaphores[] = { g_renderFinishedSemaphores[inFlightIndex] };		// 指令缓冲 结束后 的信号量
		{
			VkSubmitInfo submitInfo{};
			submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
			VkSemaphore waitSemaphores[] = { g_imageAvailableSemaphores[inFlightIndex] };
			VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
			submitInfo.waitSemaphoreCount = 1;
			submitInfo.pWaitSemaphores = waitSemaphores;		// 队列执行前 需要等待的信号量
			submitInfo.pWaitDstStageMask = waitStages;		// 需要等待的阶段, 我的理解是: 某个阶段前的指令可以执行, 但该阶段时 需要等待 信号量
			submitInfo.commandBufferCount = 1;
			submitInfo.pCommandBuffers = &g_commandBuffers[imageIndex];		// 指令缓冲对象, 但为啥是个数组?
			submitInfo.signalSemaphoreCount = 1;
			submitInfo.pSignalSemaphores = signalSemaphores;
			auto vResult = vkQueueSubmit(g_graphicsQueue, 1, &submitInfo, g_inFlightFences[inFlightIndex]); assert(vResult == VK_SUCCESS);
		}
		
		// 呈现
		{
			VkPresentInfoKHR presentInfo{};
			presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
			presentInfo.waitSemaphoreCount = 1;
			presentInfo.pWaitSemaphores = signalSemaphores;
			VkSwapchainKHR swapChains[] = { g_swapChain };
			presentInfo.swapchainCount = 1;
			presentInfo.pSwapchains = swapChains;
			presentInfo.pImageIndices = &imageIndex;
			auto vResult = vkQueuePresentKHR(g_presentQueue, &presentInfo);  assert(vResult == VK_SUCCESS);
		}

		// vkQueueWaitIdle(g_presentQueue);
		
		inFlightIndex = (++inFlightIndex) % MAX_FRAMES_IN_FLIGHT;

		if (++i > 1000) { break; }
	}
	QueryPerformanceCounter(&tEnd);

	auto timeMS = (int)((double)(tEnd.QuadPart - tStart.QuadPart) / (double)fre.QuadPart * 1000.0);
	printf("timeMS: %d\n", timeMS);

	vkDeviceWaitIdle(g_device);

	// 释放
	clearup();

	return 0;
}